﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
namespace BackgrounderService
{
    static class HookWrap
    {
        static HookWrap()
        {
            Initialization();
            set_key_call_back(KeyCB);
            set_mouse_call_back(MouseCB);
            GC.KeepAlive(MouseCB);              //prevent from collectting
            GC.KeepAlive(KeyCB);
            KeyHookState = HookState.Stop;
            MouseHookState = HookState.Stop;
            SysInfoPeriod = Properties.Settings.Default.SysinfoInterval;
            machineName= System.Environment.MachineName;
            cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", machineName);
            ramCounter = new PerformanceCounter("Memory", "% Committed Bytes In Use", String.Empty, machineName);
            diskWriteCounter = new PerformanceCounter("PhysicalDisk", "Disk Write Bytes/sec", "_Total", machineName);
            diskReadCounter = new PerformanceCounter("PhysicalDisk", "Disk Read Bytes/sec", "_Total", machineName);
            timer = new System.Timers.Timer(SysInfoPeriod);
            timer.Elapsed+=new System.Timers.ElapsedEventHandler(timerCall);
        }
        #region Events And delegate

        
       
        public static event MouseEventHandler OnClick;
        public static event KeyEventHandler OnKeyPress;
        public static event SysEventHandler OnSysInfo;

        #endregion


        #region DllImport

        public delegate void CallBack(int code, int wParam, int lParam);

        [DllImport("HookWrap.dll")]
        private static extern bool Initialization();

        [DllImport("HookWrap.dll")]
        private static extern bool install_mouse_hook();

        [DllImport("HookWrap.dll")]
        private static extern bool uninstalll_mouse_hook();

        [DllImport("HookWrap.dll")]
        private static extern bool install_key_hook();

        [DllImport("HookWrap.dll")]
        private static extern bool uninstalll_key_hook();

        [DllImport("HookWrap.dll")]
        private static extern void set_mouse_call_back(CallBack call_back);

        [DllImport("HookWrap.dll")]
        private static extern void set_key_call_back(CallBack call_back);

        #endregion

        public enum HookState { Runing, Stop, Error };
        public static HookState KeyHookState { get; private set; }
        public static HookState MouseHookState { get; private set; }

        #region C++ CallBack
        private static CallBack MouseCB = new CallBack(MouseEventCallBack);
        private static CallBack KeyCB = new CallBack(KeyEventCallBack);

        private static void MouseEventCallBack(int code, int wParam, int lParam)
        {
            System.Diagnostics.Process CurProcess = System.Diagnostics.Process.GetProcessById(wParam);
            if (OnClick != null)
                OnClick.Invoke(new MouseEventArgs(CurProcess.MainModule.ModuleName, (short)(lParam & 0x0000FFFF), (short)(lParam >> 16), DateTime.Now.ToString("s")));

        }

        private static void KeyEventCallBack(int code, int wParam, int lParam)
        {
            //Console.WriteLine("{0},{1},{2}", code, wParam, lParam);
            System.Diagnostics.Process CurProcess = System.Diagnostics.Process.GetProcessById(lParam);
            if (OnKeyPress != null)
                OnKeyPress.Invoke(new KeyEventArgs(CurProcess.MainModule.ModuleName, wParam, DateTime.Now.ToString("s")));

        }

        private static  void timerCall(object source, System.Timers.ElapsedEventArgs e)
        {
            //System.Windows.Forms.MessageBox.Show("Sys");
            OnSysInfo.Invoke(
                new SysPerfArgs(
                    (int)cpuCounter.NextValue(),
                    (int)diskWriteCounter.NextValue(), 
                    (int)diskReadCounter.NextValue(),
                    (int)ramCounter.NextValue(), DateTime.Now.ToString("s"))
                );
        }
        #endregion

        public static int SysInfoPeriod { set; get; }

        #region Methods

        public static void StartMouseHook()
        {
            if (install_mouse_hook())
                MouseHookState = HookState.Runing;
            else
                MouseHookState = HookState.Error;
        }
        public static void StopMouseHook()
        {
            if (uninstalll_mouse_hook())
                MouseHookState = HookState.Stop;
            else
                MouseHookState = HookState.Error;
        }
        public static void StartKeyHook()
        {
            if (install_key_hook())
                KeyHookState = HookState.Runing;
            else
                KeyHookState = HookState.Error;
        }
        public static void StopKeyHook()
        {
            if (uninstalll_key_hook())
                KeyHookState = HookState.Stop;
            else
                KeyHookState = HookState.Error;
        }
        public static void StartSysHook()
        {
            timer.Start();
        }
        public static void StopSysHook()
        {
            timer.Stop();
        }
        #endregion

        private static System.Timers.Timer timer;
        private static string machineName;
        private static PerformanceCounter cpuCounter = null;
        private static PerformanceCounter ramCounter = null;
        private static PerformanceCounter diskWriteCounter = null;
        private static PerformanceCounter diskReadCounter = null;
    }
}
